package cloud.seri.gateway.security.oauth2

import javax.servlet.http.Cookie

/**
 * A collection of [Cookie]s that allows modification - unlike a mere array.
 *
 *
 * Since [Cookie] doesn't implement `hashCode` nor `equals`,
 * we cannot simply put it into a `HashSet`.
 */
class CookieCollection {

    private val cookieMap = mutableMapOf<String, Cookie>()

    constructor()

    constructor(vararg cookies: Cookie) : this(cookies.asList())

    constructor(cookies: Collection<Cookie>) {
        addAll(cookies)
    }

    val size: Int
        get() = cookieMap.size

    fun isEmpty(): Boolean  = cookieMap.isEmpty()

    fun contains(element: Any): Boolean {
        return when (element){
            is String -> cookieMap.containsKey(element)
            is Cookie -> cookieMap.containsValue(element)
            else -> false
        }
    }

    fun iterator(): Iterator<Cookie>  = cookieMap.values.iterator()

    fun toArray(): Array<Cookie> {
        return cookieMap.values.toTypedArray()
    }

    fun add(cookie: Cookie): Boolean {
        cookieMap[cookie.name] = cookie
        return true
    }

    fun remove(o: Any): Boolean {
        return when (o) {
            is String -> cookieMap.remove(o) != null
            is Cookie -> cookieMap.remove(o.name) != null
            else -> false
        }
    }

    operator fun get(name: String): Cookie? {
        return cookieMap[name]
    }

    fun containsAll(elements: Collection<Any>): Boolean {
        for (o in elements) {
            if (!contains(o)) {
                return false
            }
        }
        return true
    }

    fun addAll(collection: Collection<Cookie>): Boolean {
        var result = false
        for (cookie in collection) {
            result = result or add(cookie)
        }
        return result
    }

    fun removeAll(collection: Collection<Any>): Boolean {
        var result = false
        for (cookie in collection) {
            result = result or remove(cookie)
        }
        return result
    }

    fun retainAll(collection: Collection<Any>): Boolean {
        var result = false
        val it = cookieMap.entries.iterator()
        while (it.hasNext()) {
            val e = it.next()
            if (!collection.contains(e.key) && !collection.contains(e.value)) {
                it.remove()
                result = true
            }
        }
        return result
    }

    fun clear() {
        cookieMap.clear()
    }
}
